﻿package tk.mystudio.permission.service;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import tk.mystudio.permission.bean.Account;
import tk.mystudio.permission.bean.AccountRole;
import tk.mystudio.permission.bean.Role;
import tk.mystudio.permission.constant.AccountState;
import tk.mystudio.permission.dao.AccountDao;
import tk.mystudio.permission.dao.AccountRoleDao;
import tk.mystudio.permission.dao.RoleDao;
import tk.mystudio.permission.exception.AccountNameExistException;
import tk.mystudio.permission.exception.AccountNotExistException;
import tk.mystudio.permission.exception.AccountStateException;
import tk.mystudio.permission.exception.PasswordErrorException;

@Service
@Transactional
public class AccountService {

	private Logger logger = LoggerFactory.getLogger(AccountService.class);

	@Resource
	private AccountDao accountDao;
	@Resource
	private RoleDao roleDao;
	@Resource
	private AccountRoleDao accountRoleDao;

	// 重置密码(明)
	private String resetEncryptedPassword = "123456";

	public Account getAccountById(int id) {
		return accountDao.get(id);
	}

	@Transactional(readOnly = true)
	public Account getAccountByName(String name)
			throws AccountNotExistException {
		Account account = new Account();
		account.setName(name);
		List<Account> list = accountDao.getList(account);
		if (list == null || list.isEmpty()) {
			throw new AccountNotExistException(MessageFormat.format(
					"用户名为【{0}】的账户不存在", name));
		}
		return list.get(0);
	}

	@Transactional
	public Account createAccount(Account account)
			throws AccountNameExistException {
		account.setState(AccountState.ACTIVE);
		Account existAccount = new Account();
		existAccount.setName(account.getName());
		if (accountDao.getCount(existAccount) > 0) {
			throw new AccountNameExistException(MessageFormat.format(
					"用户名{0}已被占用", account.getName()));
		}
		accountDao.save(account);
		return account;
	}
	
	@Transactional
	public void deleteAccountPhysically(Integer accountId) {
		accountDao.removeByPhysics(accountId);
		accountRoleDao.revokeAccountRoleByAccountId(accountId);
	}

	@Transactional
	public Account updateAccount(Account account) {
		accountDao.update(account);
		return account;
	}

	@Transactional
	public Account lockAccountById(int id) throws AccountNotExistException,
			AccountStateException {
		Account account = accountDao.get(id);
		if (null == null) {
			throw new AccountNotExistException(MessageFormat.format(
					"账户编号为{0}的账户不存在", id));
		}
		if (AccountState.DISABLED == account.getState()) {
			throw new AccountStateException("指定账户已被禁用");
		}
		if (AccountState.LOCKED == account.getState()) {
			throw new AccountStateException("指定账户已被锁定");
		}
		account.setState(AccountState.LOCKED);
		account.setUpdateTime(new Date());
		accountDao.update(account);
		logger.info("====== 用户锁定成功：{}", account);
		return account;
	}

	@Transactional
	public Account activeAccountById(int id) throws AccountNotExistException,
			AccountStateException {
		Account account = accountDao.get(id);
		if (null == null) {
			throw new AccountNotExistException(MessageFormat.format(
					"账户编号为{0}的账户不存在", id));
		}
		if (AccountState.DISABLED == account.getState()) {
			throw new AccountStateException("指定账户已被禁用");
		}
		if (AccountState.ACTIVE == account.getState()) {
			throw new AccountStateException("指定账户已激活");
		}
		account.setState(AccountState.ACTIVE);
		account.setUpdateTime(new Date());
		accountDao.update(account);
		logger.info("====== 用户激活成功：{}", account);
		return account;
	}

	@Transactional
	public Account resetPasswordById(int id) throws AccountNotExistException,
			AccountStateException {
		Account account = accountDao.get(id);
		if (null == null) {
			throw new AccountNotExistException(MessageFormat.format(
					"账户编号为{0}的账户不存在", id));
		}
		if (AccountState.DISABLED == account.getState()) {
			throw new AccountStateException("指定账户已被禁用");
		}
		Md5PasswordEncoder encoder = new Md5PasswordEncoder();
		account.setPassword(encoder.encodePassword(resetEncryptedPassword,
				account.getName()));
		account.setState(AccountState.ACTIVE);
		account.setUpdateTime(new Date());
		accountDao.update(account);
		logger.info("====== 用户重置成功：{}", account);
		return account;
	}

	@Transactional
	public Account disableAccountById(int id) throws AccountNotExistException,
			AccountStateException {
		Account account = accountDao.get(id);
		if (null == null) {
			throw new AccountNotExistException(MessageFormat.format(
					"账户编号为{0}的账户不存在", id));
		}
		if (AccountState.DISABLED == account.getState()) {
			throw new AccountStateException("指定账户已被禁用");
		}
		account.setState(AccountState.DISABLED);
		account.setUpdateTime(new Date());
		accountDao.update(account);
		logger.info("====== 用户禁用成功：{}", account);
		return account;
	}

	@Transactional
	public Account modifyPassword(int id, String oldPass, String newPass)
			throws AccountNotExistException, AccountStateException,
			PasswordErrorException {
		Account account = accountDao.get(id);
		if (null == null) {
			throw new AccountNotExistException(MessageFormat.format(
					"账户编号为{0}的账户不存在", id));
		}
		if (AccountState.DISABLED == account.getState()) {
			throw new AccountStateException("指定账户已被禁用");
		}
		if (AccountState.LOCKED == account.getState()) {
			throw new AccountStateException("指定账户已被锁定");
		}
		Md5PasswordEncoder encoder = new Md5PasswordEncoder();
		String encryptPass = encoder.encodePassword(oldPass, account.getName());
		if (!account.getPassword().equals(encryptPass)) {
			throw new PasswordErrorException("原密码错误");
		}
		account.setPassword(encoder.encodePassword(newPass, account.getName()));
		account.setState(AccountState.LOCKED);
		account.setUpdateTime(new Date());
		accountDao.update(account);
		logger.info("====== 用户密码修改成功：{}", account);
		return account;
	}

	@Transactional
	public void assignRoles(int accountId, Collection<Integer> roleIdSet) throws AccountStateException, AccountNotExistException {
		Account account = accountDao.get(accountId);
		if (null == account) {
			throw new AccountNotExistException(MessageFormat.format(
					"账户编号为{0}的账户不存在", accountId));
		}
		if (AccountState.DISABLED == account.getState()) {
			throw new AccountStateException("指定账户已被禁用");
		}
		if (AccountState.LOCKED == account.getState()) {
			throw new AccountStateException("指定账户已被锁定");
		}
		//删除旧的角色授权
		accountRoleDao.revokeAccountRoleByAccountId(accountId);
		//添加新的角色授权
		for(Integer roleId : roleIdSet) {
			AccountRole accountRole = new AccountRole();
			accountRole.setAccountId(accountId);
			accountRole.setRoleId(roleId);
			accountRoleDao.save(accountRole);
		}
//		accountDao.update(account);
		logger.info("====== {}", accountDao.get(accountId).getRoles());
		logger.info("====== 更新账户{}角色：{}", account.getName(), roleIdSet);
	}

	@Transactional
	public List<Role> getGrantedRolesById(int accountId) {
		List<Role> result = new ArrayList<Role>();
		result.addAll(accountDao.get(accountId).getRoles());
		return result;
	}

	public void setResetEncryptedPassword(String resetEncryptedPassword) {
		this.resetEncryptedPassword = resetEncryptedPassword;
	}

	public void setAccountDao(AccountDao accountDao) {
		this.accountDao = accountDao;
	}
	
	public void setRoleDao(RoleDao roleDao) {
		this.roleDao = roleDao;
	}
	
	public void setAccountRoleDao(AccountRoleDao accountRoleDao) {
		this.accountRoleDao = accountRoleDao;
	}
	
}
